import Tools from "../../framework/utils/Tools";
import DebugUtil from "../../framework/utils/DebugUtil"; 
import EventManager from "../../framework/core/EventManager";   
import { Events } from "../constants/Events";
import PlayerMgr from "../data/PlayerMgr";

/**
 * ws wss封装网络收发游戏逻辑
 */
export default class PomeloManager{
    //@ts-ignore
    protected pomelo = window.pomelo;

    gateRoute:string     = "gate.gateHandler.queryEntry";
    coonnetRoute:string  = "connector.entryHandler.enter";
    logicRoute:string    = "logic.playerHandler.handler";
    //是否第一次连接
    isFristConnect:boolean = false;
    //连接状态  1连接中  -1已断开
    isDisconnect:number = -1;
    //缓存消息id
    recordMsgDict = {}
    //登陆用户uid
    protected uid:number = 0;

    private static _ins: PomeloManager = null;
    
    public static get ins(): PomeloManager {
        if (this._ins == null) {
            this._ins = new PomeloManager();
            this._ins.init();
        }
        return this._ins;
    }

    public resetNet(){
        this.isFristConnect = false;
        this.isDisconnect = -1;
        this.recordMsgDict = {};
    }
      

    private init(){
        this.pomelo.on('disconnect', this.onCloseWebScoket.bind(this) );
        this.pomelo.on('xfp_error' , this.onErrorWebScoket.bind(this) );
        this.pomelo.on('onData', this.onSyncRespMsg.bind(this) ); 
    }
 
    // 登录网关服
    loginGateServer( host:string, port:string, uid:number ) {  
        this.uid = uid;
        this.pomelo.init(
            {
                host: host,
                port: port,
                log: true
            },
            this.onGateLoginCallBack.bind(this)
        );
    }

    private onGateLoginCallBack(){
        this.pomelo.request(
            this.gateRoute, 
            {
                uid: this.uid
            },
            this.onGateRequestCallBack.bind(this)
        );   
    }


    private onGateRequestCallBack(data){
        DebugUtil.log("登陆网关返回",`${data.host}:${data.port}`)
        this.pomelo.disconnect(); 
        if( data.code != 200 ) {
           cc.error("服务异常  500"); 
           EventManager.emit(Events.NET_STATE,"服务异常 状态500")
           return;
       }
       // 登录链接服
       this.initConnectorServer( data.host, data.port );

    }

    //连接服务器
    private  initConnectorServer(host:string, port:string ){ 
        DebugUtil.log("连接游戏服务器",`${host}:${port}`)
        this.pomelo.init(
            {
                host: host,
                port: port,
                log: true
            },
            this.onConnectorCallBack.bind(this)
        );
    }
    //连接服务器返回
    private onConnectorCallBack(){ 
        // 登录链接服
        this.pomelo.request(
            this.coonnetRoute, 
            {
                uid: this.uid,
                //oalev:GData.OaLev,
            },
            this.onLoginConnectorSuccessCallBack.bind(this)
        );   
    }
    
    //登陆返回数据
    private onLoginConnectorSuccessCallBack(data){
        if( data.error ) { 
            cc.log( "onLoginConnectorSuccessCallBack", data.error );
            return;
        }
        if( Tools.isValid(data.ret) && data.ret !== 0 ){ 
            //GameTools.topTips(ErrorCodeMgr.ins.getString(data.ret)); 
            return;
        } 

        if( Tools.isValid(data.code) && data.code !== 0 ){
            cc.log( "onLoginConnectorSuccessCallBack code:" + data.code );
            EventManager.emit(Events.ERROR_CODE,data.code);
            return;
        }

        if( Tools.isEmpty(data.data) ){
            cc.log( "链接服超时" );
            return;
        } 

        //登陆数据
        if(data && data.data){
            PlayerMgr.getInstance().init(data.data);
        }
        //登陆成功后就开发监听错误
        this.isFristConnect = true;
        this.isDisconnect = 1 ;  
        EventManager.emit(Events.LOGIN_GAME_SCUESS);
    } 


    /**
     * @api {function} PomeloManager.getInstance().sendMsg 发送网络消息到服务器
     * @apiName sendMsg
     * @apiGroup NetMgr 
     * @apiParam {Number} msgID 消息ID
     * @apiParam {Array} mssage 发送数据
     * @apiParam {function} callFunc 回调
     * @apiParam {boolean} isLimit=true 是否限制发送间隔
     * @apiExample {js} Request-Example: 
     *      _G.NetMgr.sendMsg(msgID,mssage,callFunc,isLimit) 
     */
    sendMsg( msgID:number, mssage:any = null, callFunc:Function = null, isLimit:boolean=true) {
         
        if ( Tools.isEmpty( msgID ) ) {
            cc.log( "msgID don't null !!!" );
            return;
        }
        if( msgID < 0 ) {
            cc.log("msgID = 0 mssage:" + JSON.stringify(mssage))
            return;
        }
        if ( this.isDisconnect <= 0 ) {
            cc.log( "conn not find!" );
            return;
        }
        if( Tools.isEmpty(isLimit) ){
            isLimit = true;
        }
        var cTime = Math.floor(Date.now()/1000);
        if ( isLimit && cTime-this.recordMsgDict[msgID]<1 ) {
            if( Tools.isValid(callFunc) && typeof (callFunc) === "object") {
                callFunc = null;
            }
            cc.log( "消息发送过快！" );
            return false;
        }

        if(mssage)
            DebugUtil.log(`${msgID} 发送请求 ${cTime}`,JSON.stringify(mssage))

        
        this.recordMsgDict[msgID] = cTime;  
        this.pomelo.request(
            this.logicRoute, 
            {
                msgID: msgID,
                data: mssage
            },
            this.onLogicMsgCallBack.bind(this, callFunc)
        );
    }


    /**
     * 所有游戏内请求逻辑返回在这
     */
    private onLogicMsgCallBack(callFunc:Function, msg:any ){

        if( Tools.isEmpty(msg) ){
            cc.log("msg is null====>")
            return;
        } 
        if(msg.msgID != 1003){
            DebugUtil.log(`服务器消息返回:${msg.msgID} ${ Math.floor(Date.now()/1000)}`,JSON.stringify(msg)) 
        }
        
        if(msg.code === 500) {
            EventManager.emit(Events.NET_STATE,"服务器开小差了~~~！")
            cc.log("NET",["sendMessage  server is return error 500 "]); 
            return;
        }
    
        if (Tools.isEmpty(msg)) {
            cc.log("返回空消息结构")
            return;
        }

        //更新时间
        if(msg.data && msg.data.ctime){
            Tools.serverTime = msg.data.ctime;
            Tools.lastSendTime = Tools.getTime();
        }

        
        if(Tools.isValid(msg.data) && Tools.isValid(msg.data.update)){  
            PlayerMgr.getInstance().synchronPlayerData(msg.data.update) ;  
        } 

        callFunc && callFunc(msg);

        if (msg.ret !== 0 ){  
            cc.log("消息返回 ret 不为 0 ret:" + msg.ret);
            EventManager.emit(Events.ERROR_CODE,msg);
            return;
        }

        //通知游戏 
        EventManager.emit(`${msg.msgID}`, msg )
    }

    private onCloseWebScoket(){ 
        if( this.isFristConnect == false ) return;
        cc.error("网络断开啦");
        EventManager.emit(Events.NET_STATE,"网络断开啦")
        this.isDisconnect = -1;
    }

    private onErrorWebScoket(event){
        if(event){
            if(typeof(event) == "object"){
                console.log( JSON.stringify(event) )
            }else{
                console.log( event )
            } 
        }
        cc.error("网络出错啦");  
        EventManager.emit(Events.NET_STATE,"网络出错啦")
        this.isDisconnect = -1; 
    }
    
    private onSyncRespMsg(msg){
        DebugUtil.log( "服务器推送消息:" + JSON.stringify(msg));  
        //通知游戏 
        if( Tools.isEmpty(msg) ){ return;  }   
        if(msg.code === 500) {   return; }
    
        if (Tools.isEmpty(msg)) {
            cc.log("返回空消息结构")
            return;
        }
 
        //更新时间
        if(msg.data && msg.data.ctime){
            Tools.serverTime = msg.data.ctime;
            Tools.lastSendTime = Tools.getTime();
        }

        if(Tools.isValid(msg.data) && Tools.isValid(msg.data.update)){  
            PlayerMgr.getInstance().synchronPlayerData(msg.data.update) ;  
        }  
 
        if (msg.ret !== 0 ){  
            cc.log("消息返回 ret 不为 0 ret:" + msg.ret);
            EventManager.emit(Events.ERROR_CODE,msg.ret);
            return;
        }
        //通知游戏 
        EventManager.emit(`${msg.msgID}`, msg )
    }


    
}


